import Feature from "../Feature";
import { IPoint, IPixelPos, IRelativePos, ITxt } from "../../Interface";
import { Utils } from "../../utils";
import { ClassName } from "@/Constants";

// 线段元素
class Line extends Feature {

    lineWidthArr: number[] = [];
    label: ITxt | null = null;

    constructor(pointArr: IRelativePos[] = []) {
        super(pointArr);
        this.className = ClassName.LINE;
        this.isClosePath = false;
        this.hoverStyle = '#4A7EBA'
        this.strokeStyle = '#60A6F7';
    }

    override draw(ctx: CanvasRenderingContext2D, pointArr: IPixelPos[], lineWidth: number, lineDashArr: number[]) {
        if (pointArr.length <= 1) return;
        const path = super.draw(ctx, pointArr, lineWidth, lineDashArr)
        this.drawLabel(ctx, Utils.getMidTwoOfPoints(pointArr), lineWidth);
        return path;
    }

    setBezierPnts(bezierPnts = this.bezierPnts) {  // 设置贝塞尔控制点位置
        this.bezierPnts = bezierPnts;
        this.getGeneratePointArr()
    }

    getGeneratePointArr(...args: any) {
        if (!this.getGeneratePointArrFn) this.getGeneratePointArrFn = this.getStraightPoints;
        const originPnts = this.pointArr.filter(f => !f.generated);
        return this.getGeneratePointArrFn(originPnts, ...args);
    }

    getStraightPoints(pointArr: IPoint[] = this.pointArr) {
        if (this.bezierPnts.length > 0 && this.cbTransform) {
            let curveNodes: IPoint[] = []
            for (let i = 0; i < pointArr.length - 1; i++) {
                if (this.bezierPnts[i]) {
                    const curvePnts = Utils.getPntsOf2Bezier(pointArr[i], this.bezierPnts[i], pointArr[i + 1], 20).map((p, j) => ({ x: p.x, y: p.y, generated: j != 0 }))
                    curveNodes = curveNodes.concat(curvePnts);
                }
            }
            curveNodes.push(pointArr[pointArr.length - 1]);
            return curveNodes;
        } else {
            pointArr.forEach((curP, i) => {
                const prevP = pointArr[i - 1];
                if (prevP) {
                    let mid = Utils.getMidOfTwoPnts(curP, prevP);
                    this.bezierPnts[i - 1] = mid;
                }
            })
            return pointArr;
        }
    }

    // getCurvePoints(pointArr: IPoint[] = this.pointArr) {
    //     const newPnts: IPoint[] = []
    //     const per = .8
    //     pointArr.forEach((curP, i) => {
    //         if (i > 0) {
    //             const nextP = pointArr[i];
    //             const prevP = pointArr[i - 1];
    //             const vct = Utils.getVector(nextP, curP);
    //             const ctrlP = Utils.getPntInVct(nextP, vct, Utils.getLenOfTwoPnts(nextP, curP) * per)
    //             const curvePnts = Utils.getPntsOf2Bezier(prevP, ctrlP, curP, 20).map((p, j) => ({ x: p.x, y: p.y, generated: j != 0 }))
    //             newPnts.push(...curvePnts)
    //         }
    //     })
    //     return newPnts;
    // }

    drawLabel(ctx: CanvasRenderingContext2D, pointArr: [IPoint, IPoint], lineWidth = 0) {
        if (this.label) {
            const startP = pointArr[0];
            const endP = pointArr[1];
            if (startP && endP) {  // 只接受起点和终点, 文本
                const mid = Utils.getMidOfTwoPnts(startP, endP);
                ctx.save()
                if (this.label.autoRotate) {
                    let angle = Utils.getAngleOfTwoPnts(startP, endP);   // 获取两个点 水平方向上的角度
                    if ((angle > 90 && angle < 180 || angle < -90 && angle > -180)) {
                        angle += 180  // 镜像翻转,文字始终朝上
                    }
                    this.rotateCtx(ctx, mid, angle);
                }
                const fontSize = Feature.Render.getRatioSize(this.label.fontSize);
                const offsetX = Feature.Render.getRatioSize(this.label.offset.x);
                const offsetY = Feature.Render.getRatioSize(this.label.offset.y);
                ctx.font = `${fontSize}px ${this.label.fontFamily}`;
                const { width } = ctx.measureText(this.label.content);  // 文本的宽度
                if (this.label.fill) {
                    const padding = this.label.fillPadding || 0;
                    ctx.fillStyle = this.label.fill;
                    ctx.fillRect(mid.x - width / 2 + offsetX - padding, mid.y + offsetY - fontSize + lineWidth / 2 - padding, width + padding * 2, fontSize + padding * 2);
                }
                ctx.fillStyle = this.label.color;
                ctx.fillText(this.label.content, mid.x - width / 2 + offsetX, mid.y - lineWidth + offsetY);
                ctx.restore()
            }
        }
    }

    override getSvg(pointArr: IPixelPos[] = [], lineWidth: number = 1) {
        let path = super.getSvg(pointArr, lineWidth);
        if (this.label && pointArr.length >= 2) {
            const [startP, endP] = Utils.getMidTwoOfPoints(pointArr);
            const center = Utils.getMidOfTwoPnts(startP, endP);
            let angle = 0;
            if (this.label.autoRotate) {
                angle = Utils.getAngleOfTwoPnts(startP, endP);   // 获取两个点 水平方向上的角度
                if (angle > 90 && angle < 180 || angle < -90 && angle > -180) {
                    angle += 180  // 镜像翻转,文字始终朝上
                }
            }
            const fontSize = Feature.Render.getRatioSize(this.label.fontSize);
            const width = fontSize * this.label.content.length;
            path += `
            <g transform="rotate(${angle} ${center.x} ${center.y})" opacity="${this.opacity}">
                ${`<text x="${center.x - width / 2}" y="${center.y}" dominant-baseline="hanging" style="fill:${this.label.color}; font-family: '${this.label.fontFamily}'; font-size: ${fontSize}; font-weight:${this.label.bolder ? 'bolder' : ''};"
                >${this.label.content}</text>`}
            </g>`
        }
        return path;
    }
}

export default Line;